package com.tedu.api.io;

import org.junit.Test;

import java.io.*;
import java.nio.Buffer;
import java.nio.charset.StandardCharsets;

/**
 * 标准IO流---目的：数据传输  输出文本，图片
 * java定义一套标准流-->数据传输-->创建流：直接创建某个流对象。
 * 标准流规则①：方向划分---输入流和输出流
 *             输入流：流入--->文件--->相对于程序--->文件往程序走
 *             InputStream(抽象类：定义所有读的写法)【学习：子实现类】
 *             输出流：写出--->文件--->相对于程序--->程序写出
 *             OutputStream(抽象类：定义所有读的写法)
 *         ②：功能划分
 *         低级流【节点流】：是建立在程序与数据源之间的“管道”
 *               功能：负责搬运的数据流，输入流于输出流都有自己的低级流
 *               特点：一个字节一个字节读或者写的方法
 *        FileOutputStream  低级流继承InputStream ---文件输出流：写
 *        FileInputStream  低级流继承OutputStream ---文件输出流：读
 *        高级流【处理流】：不能直接创建对象，不能独立存在
 *              功能：专门处理低级流以及其他高级的流
 *              特点：搬运数据时，实现具体功能：效率提高流
 *
 *  --总结：输入流和输出流，具备功能：低级流与高级流
 *  实际使用：明确使用具体流，每个流都有自己功能
 */
public class IOAPI {
    /**
     *                               文件输入流
     *         输入流        低级流--
     *标准流   方向：      功能：         文件输出流：FileOutputStream  √
     *            输出流     高级流
     * 需求：写出一个文件fos.txt
     *
     * FileOutputStream 构造器使用
     * new FileOutputStream ("路径+文件全称")
     * new FileOutputStream ("路径+文件全称"，boolean append)
     * 写出文件的同时实现追加效果，第二个参数：true  追加
     *                                  false  默认不追加
     * new FileOutputStream(File file,boolean append);
     *  写出文件，采用File传入路径+全称
     */
    @Test
    public void testFOS() throws IOException {
    /* RandomAccessFile raf=
    new RandomAccessFile("fos.txt","rw");*/
    //低级流---文件输出流对象---从程序中写出“文件：数据”
    FileOutputStream fos=new FileOutputStream("fos.txt");
    //需求：fos.txt 增加一行文本,每次运行实现追加效果
    String say="独one无two";//字符串由字符数组构成--数组的功能--getBytes()转换为字节数组
    //输出流--写功能：write(byte[] b)  写出字节数组
    fos.write(say.getBytes("UTF8"));
    //必须关闭流--目的：节省内存开销
    fos.close();
    }
    /**
     * 文件输入流：读入操作
     * FileOutputStream 文件输入流
     * read()  返回一个读取一个字节--效率低
     * read(字节数组byte[]  b)
     * 返回一个“指定字节数组：空间大小”的读取---效率高
     * 需求：读入fos.txt文件内容
     */
    @Test
    public void testFIS() throws IOException {
    //创建文件输入流---读入：fos.txt
    FileInputStream fis=new FileInputStream("fos.txt");
    //读入效率高：创建字节数组-指定空间为：10KB
    byte[] data=new byte[1024*10];
    //读入操作：read(字节数组)   |  以10KB读入数据
    int len=fis.read(data);
    //写出：文本---字符串---针对流操作，提供构造器
    //                   文件按照指定字节数组空间“写入程序中
    //                    从0开始写入程序，写入到-1结束
    //                    len:十进制转换为二进制，写入，不等-1，一直写入
    //一次性将给定数据按照字节数组指定空间的大小，写出成字符串
    String str=new String(data,0,len);
    System.out.println("打印Fos.txt文件："+str);
    }
    /**
     * 需求：利用标准流实现视频复制粘贴
     */
    @Test
    public void testCV() throws IOException {
    //1.从”复制文件.mp4"复制 操作--读入
     FileInputStream fis=new FileInputStream("复制视频.mp4");
    //2.创建新文件“新文件.mp4" 粘贴 操作---写出
    FileOutputStream fos=new FileOutputStream("复制视频.mp4");
    //3.保存每次读取的数据【字节量--int】
    int len=-1;
    //4.一直 从”复制文件.mp4“  进行读入操作,不等于-1  一直读
    //(len=fis.read())!=-1
    while ((len= fis.read())!=-1){//true
    //4.1同时 写出”新文件.mp4“
    fos.write(len);
    }
    //5.关闭流      ---测：效率---正常播放
    fis.close();
    fos.close();
    }
    /**
     * 需求：利用标准流实现视频复制粘贴---效率低
     *                               效率高--->空间执行力：自定100KB
     * 【高级流】BufferedInputStream  缓冲输入流--提升效率--缓冲区：字节数组【长度按照文件大小合理分配】
     *         BufferedOutputStream  缓冲输入流--提升效率--缓冲区：字节数组【长度按照文件大小合理分配】
     *高级流使用方式：①处理低级流，套在低级流上
     *             ②直接使用高级流的方法
     *             ③高级流不能直接创建【不能独立存在】
     */
    @Test
    public void testCVS() throws IOException {
    //1.创建低级流：读入”复制视频.mp4“
    FileInputStream fis=new FileInputStream("复制视频.mp4");
    //1.创建高级流：套在低级流上【自带缓冲区：字节数组】
    BufferedInputStream bis=new BufferedInputStream(fis);
    //2.创建低级流：写出”高效视频.mp4“
    FileOutputStream fos=new FileOutputStream("高效视频.mp4");
    //2.创建高级流：套在低级流上【自带缓冲区：字节数组】
    BufferedOutputStream bos=new BufferedOutputStream(fos);

    //3.保存数据
    int len=-1;
    //4.高级流--低级流方法一致---read()读取内嵌缓冲区【字节数组】
    //高级流--低级流方法一致---write()读取内嵌缓冲区【字节数组】
    //一直从"复制视频.mp4“读取数据 只要不等于-1，就一直读
    //(len=bis.read())!=-1
    long start=System.currentTimeMillis();  //系统时间毫秒数
    while((len=bis.read())!=-1){
    bos.write(len);
       }
    long end=System.currentTimeMillis();
    System.out.println("缓冲流【自带缓冲区】："+(end-start)+"毫秒数");
    //关闭流---  高级流与低级流：都关--->高级流间接性关闭低级流
    bis.close();//高级流--缓冲输入流
    bos.close();//高级流--缓冲输出流

    }
    /**
     * 高级流---缓冲流【内嵌缓冲区】
     * BufferedOutputStream  缓冲输入流
     *
     * 需求：通过缓冲输出流实现从程序写出文件：bos.txt,写出内容
     */
    @Test
    public void testBOS() throws IOException {
    //1.创建低级流-->bos.txt
    FileOutputStream fos=new FileOutputStream("bos.txt");
    //2.创建高级流-->缓冲区：字节数组--合理【传输效率】
    BufferedOutputStream bos=new BufferedOutputStream(fos);
    //3.写出文本内容
    String str="50 块钱设计的再好看，也不如100块钱招人稀罕~~";
    //4.写出到 bos.txt 文件中:字符串转成字节数组--写出
    bos.write(str.getBytes());
    //5.将缓冲区数据一次性写出   flush()
    //bos.flush();
    bos.close();   //关闭流---一定把缓冲区数据全部写出
    }
    /**
     * 标准IO流---成对【低级流+高级流】结合异常---数据传输---成功【异常需要捕获】
     * 需求：重构 testBOS()  单元测试
     */
    @Test
    public void testBOSIO(){
    //1.置空流---提升所有流作用域：使用范围
    FileOutputStream fos=null;//低级流：搬运数据
    BufferedOutputStream bos=null;//高级流：缓冲输出液
    //2.捕获流异常并且做出处理
    try {
      fos=new FileOutputStream("bos.txt");//低级流
      bos=new BufferedOutputStream(fos);//高级流：缓冲区：字节数组
      bos.write("独一无二".getBytes());
      bos.flush();
      } catch (FileNotFoundException e) {//IO流“小”异常
      e.printStackTrace();
      }catch (IOException e) {//IO流”中“异常：小异常父类
      e.printStackTrace();
      } catch (Exception e) {//"大“异常 Exception
      e.printStackTrace();
      }finally {//一定执行代码块
      //3.关闭流---高级流--释放资源
      //判断：高级流不为null，关闭
      if (bos!=null)
      try {
      bos.close();
      } catch (IOException e) {
      e.printStackTrace();
      }
    }
    }


    @Test
    public void testFOSIO(){
    FileOutputStream fos=null;
    try {
    fos=new FileOutputStream("fos.txt");
    fos.write("独一有二".getBytes());
    fos.flush();
    }catch (FileNotFoundException e){
        e.printStackTrace();
    }
    catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e){
        e.printStackTrace();
    } finally {
    if (fos!=null)
    try {
    fos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    }
    }


    @Test
    public void testFISIO(){
    FileInputStream fis=null;
    byte[] data=new byte[0];
    int len=0;
    try {
    fis=new FileInputStream("fos.txt");
    data=new byte[1024*10];
    len= fis.read();
    } catch (FileNotFoundException e){
       e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }catch (Exception e){
       e.printStackTrace();
    } finally {
    String str=new String(data,0,len);
    if (fis!=null)
    try {
    fis.close();
    } catch (IOException e) {
       e.printStackTrace();
    }
        System.out.println("打印Fos.txt文件："+str);

    }
    }


    @Test
    public void testCVIO(){
    FileInputStream fis=null;
    FileOutputStream fos=null;
    try {
    fis=new FileInputStream("复制视频.mp4");
    fos=new FileOutputStream("新文件1.mp4");
    int len=-1;
    while((len=fis.read())!=-1){
    fos.write(len);
    }
    } catch (FileNotFoundException e){
        e.printStackTrace();
    }
    catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e){
        e.printStackTrace();
    } finally {
    if (fis!=null)
    try {
    fis.close();
    } catch (IOException e) {
       e.printStackTrace();
     }
    }
    }


    @Test
    public void testCVSIO(){
    FileInputStream fis=null;
    BufferedInputStream bis=null;
    FileOutputStream fos=null;
    BufferedOutputStream bos=null;
    try {
    fis=new FileInputStream("复制视频.mp4");
    bis=new BufferedInputStream(fis);
    fos=new FileOutputStream("高效视频.mp4");
    bos=new BufferedOutputStream(fos);
    int len=-1;
    while((len= bis.read())!=-1){
    bos.write(len);
    }
    }catch (FileNotFoundException e){
        e.printStackTrace();
    } catch (IOException e) {
       e.printStackTrace();
    }catch (Exception e){
        e.printStackTrace();
    } finally {
    if (bos!=null)
    try {
    bos.close();
    } catch (IOException e) {
       e.printStackTrace();
    }
    if (bis!=null)
    try {
    bis. close();
    } catch (IOException e) {
       e.printStackTrace();
    }
    }
    }
}
